﻿using LM.Negocio.Objetos;

namespace LM.Negocio.Validadores
{
    using System;
    using System.Linq;

    using LM.InterfacesFabricas.Interfaces.Repositorios;

    public class ValidadorDeTabelaPreco : ValidadorAbastrato
    {
        private TabelaPreco _objetoValidado;

        private IRepositorioDeConsultaDeObjetos<TabelaPreco> _repositorioDeTabelaPreco;

        public ValidadorDeTabelaPreco(IRepositorioDeConsultaDeObjetos<TabelaPreco> repositorioDeTabelaPreco)
        {
            if (repositorioDeTabelaPreco == null)
            {
                throw new ArgumentNullException("repositorioDeTabelaPreco");
            }

            this._repositorioDeTabelaPreco = repositorioDeTabelaPreco;
        }

        public void ValideGravacao(TabelaPreco tabela)
        {
            if (tabela == null)
            {
                throw new ArgumentNullException("tabela");
            }

            _objetoValidado = tabela;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideDataInicialNaoInformado();
            ValideNaoInformadoAoMenosUmItem();

            base.GarantaSucesso();
        }

        public void ValideAtualizacao(TabelaPreco tabela)
        {
            if (tabela == null)
            {
                throw new ArgumentNullException("tabela");
            }

            _objetoValidado = tabela;
            base.LimpeInconsistencias();

            ValideCodigoNaoInformado();
            ValideNomeNaoInformado();
            ValideDataInicialNaoInformado();
            ValideNaoInformadoAoMenosUmItem();

            base.GarantaSucesso();
        }

        public void ValideExclusao(TabelaPreco tabela)
        {
            if (tabela == null)
            {
                throw new ArgumentNullException("tabela");
            }

            _objetoValidado = tabela;
            base.LimpeInconsistencias();

            ValideGaragemNaoCadastrado();

            base.GarantaSucesso();
        }

        private void ValideCodigoNaoInformado()
        {
            if (_objetoValidado.Codigo < 1)
            {
                AdicioneInconsistencia("Nome não informado.");
            }
        }

        private void ValideNomeNaoInformado()
        {
            if (String.IsNullOrWhiteSpace(_objetoValidado.Nome))
            {
                AdicioneInconsistencia("Nome não informado.");
            }
        }

        private void ValideDataInicialNaoInformado()
        {
            if (_objetoValidado.DataFim == null)
            {
                AdicioneInconsistencia("Data inicial não informada");
            }
        }

        private void ValideNaoInformadoAoMenosUmItem()
        {
            if (_objetoValidado.ItemTabela == null || _objetoValidado.ItemTabela.Count < 1)
            {
                AdicioneInconsistencia("Nenhum Item da tabela foi informado.");
            }
            else
            {
                foreach (var item in _objetoValidado.ItemTabela)
                {
                    ValideCustoPeriodoItem(item);
                    ValidePeriodoNaoInformado(item);
                    ValideCustoAdicionalItem(item);
                    ValideDiasSemanaPeriodo(item);
                }
            }
        }

        private void ValideCustoPeriodoItem(ItemTabelaPreco item)
        {
            if (item != null && item.CustoPeriodo <= 0)
            {
                AdicioneInconsistencia("Custo do período deve ser maior que 0 (zero).");
            }
        }

        private void ValidePeriodoNaoInformado(ItemTabelaPreco item)
        {
            if (item != null && item.Periodo == null)
            {
                AdicioneInconsistencia("Período inicial não informado.");
            }
        }

        private void ValideCustoAdicionalItem(ItemTabelaPreco item)
        {
            if (item != null && item.CustoAdicional < 0)
            {
                AdicioneInconsistencia("Custo adicional não pode ser menor que 0 (zero).");
            }
        }

        private void ValideDiasSemanaPeriodo(ItemTabelaPreco item)
        {
            if (item.DiasSemanaItemTabelaPrecos != null && item.DiasSemanaItemTabelaPrecos.Count > 0)
            {
                if (item.DiasSemanaItemTabelaPrecos.Any(d => d.PeriodoDoDia == null || d.PeriodoDoDia.Count == 0))
                {
                    AdicioneInconsistencia("Existe definição de dia da semana para a tabela de preços, sem informa ao menos período do dia.");
                }
            }
        }

        private bool EnderecoJaCadastrado()
        {
            return _repositorioDeTabelaPreco.Consulte(m => m.Id == _objetoValidado.Id).Any();
        }

        private void ValideGaragemNaoCadastrado()
        {
            if (!EnderecoJaCadastrado())
            {
                AdicioneInconsistencia("Não existe tabela de preço cadastrada.");
            }
        }
    }
}
